package com.flowplan.websocket.service;

import com.flowplan.websocket.dto.CollaborationMessage;
import com.flowplan.websocket.dto.UserStatusMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 实时状态同步服务
 * 处理用户在线状态同步和操作状态更新
 * 利用Java 21虚拟线程优化并发性能
 */
@Slf4j
@Service
public class RealtimeStateService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    private static final String USER_ONLINE_KEY = "realtime:online:project:%d";
    private static final String USER_ACTIVITY_KEY = "realtime:activity:project:%d";
    private static final String OPERATION_SYNC_KEY = "realtime:operation:project:%d";

    /**
     * 用户上线
     */
    public void userOnline(Long projectId, String userId, String username) {
        Thread.startVirtualThread(() -> {
            try {
                String onlineKey = String.format(USER_ONLINE_KEY, projectId);
                
                UserStatusMessage statusMessage = new UserStatusMessage();
                statusMessage.setUserId(userId);
                statusMessage.setUsername(username);
                statusMessage.setProjectId(projectId);
                statusMessage.setOnline(true);
                statusMessage.setStatus("ACTIVE");
                statusMessage.setLastActivity(LocalDateTime.now());
                
                // 存储到Redis
                redisTemplate.opsForHash().put(onlineKey, userId, statusMessage);
                redisTemplate.expire(onlineKey, 24, TimeUnit.HOURS);
                
                // 广播用户上线状态
                messagingTemplate.convertAndSend(
                    "/topic/collaboration/" + projectId + "/users",
                    statusMessage
                );
                
                log.info("用户 {} 在项目 {} 中上线", username, projectId);
                
            } catch (Exception e) {
                log.error("处理用户上线异常: projectId={}, userId={}", projectId, userId, e);
            }
        });
    }

    /**
     * 用户下线
     */
    public void userOffline(Long projectId, String userId) {
        Thread.startVirtualThread(() -> {
            try {
                String onlineKey = String.format(USER_ONLINE_KEY, projectId);
                
                // 获取用户信息
                UserStatusMessage statusMessage = (UserStatusMessage) redisTemplate.opsForHash().get(onlineKey, userId);
                if (statusMessage != null) {
                    statusMessage.setOnline(false);
                    statusMessage.setStatus("OFFLINE");
                    
                    // 广播用户下线状态
                    messagingTemplate.convertAndSend(
                        "/topic/collaboration/" + projectId + "/users",
                        statusMessage
                    );
                }
                
                // 从Redis中移除（无论用户是否存在）
                redisTemplate.opsForHash().delete(onlineKey, userId);
                
                log.info("用户 {} 在项目 {} 中下线", userId, projectId);
                
            } catch (Exception e) {
                log.error("处理用户下线异常: projectId={}, userId={}", projectId, userId, e);
            }
        });
    }

    /**
     * 更新用户活动状态
     */
    public void updateUserActivity(Long projectId, String userId, String activity, String resourceId) {
        Thread.startVirtualThread(() -> {
            try {
                String onlineKey = String.format(USER_ONLINE_KEY, projectId);
                String activityKey = String.format(USER_ACTIVITY_KEY, projectId);
                
                // 更新在线状态中的活动信息
                UserStatusMessage statusMessage = (UserStatusMessage) redisTemplate.opsForHash().get(onlineKey, userId);
                if (statusMessage != null) {
                    statusMessage.setStatus(activity);
                    statusMessage.setCurrentResourceId(resourceId);
                    statusMessage.setLastActivity(LocalDateTime.now());
                    
                    redisTemplate.opsForHash().put(onlineKey, userId, statusMessage);
                    
                    // 广播活动状态更新
                    messagingTemplate.convertAndSend(
                        "/topic/collaboration/" + projectId + "/activity",
                        statusMessage
                    );
                }
                
                // 记录活动历史（无论用户是否在线）
                String activityRecord = String.format("%s:%s:%s:%s", 
                    userId, activity, resourceId, LocalDateTime.now());
                redisTemplate.opsForList().leftPush(activityKey, activityRecord);
                redisTemplate.opsForList().trim(activityKey, 0, 99); // 保留最近100条记录
                redisTemplate.expire(activityKey, 1, TimeUnit.HOURS);
                
                log.debug("用户 {} 在项目 {} 中的活动状态更新: {}", userId, projectId, activity);
                
            } catch (Exception e) {
                log.error("更新用户活动状态异常: projectId={}, userId={}, activity={}", 
                         projectId, userId, activity, e);
            }
        });
    }

    /**
     * 同步操作状态
     */
    public void syncOperation(Long projectId, String userId, String operationType, 
                             String resourceId, Map<String, Object> operationData) {
        Thread.startVirtualThread(() -> {
            try {
                CollaborationMessage syncMessage = new CollaborationMessage();
                syncMessage.setMessageType("OPERATION_SYNC");
                syncMessage.setOperationType(operationType);
                syncMessage.setUserId(userId);
                syncMessage.setProjectId(projectId);
                syncMessage.setResourceId(resourceId);
                syncMessage.setData(objectToJson(operationData));
                syncMessage.setTimestamp(LocalDateTime.now());
                
                // 广播操作同步消息
                messagingTemplate.convertAndSend(
                    "/topic/collaboration/" + projectId + "/operations",
                    syncMessage
                );
                
                // 记录操作历史
                String syncKey = String.format(OPERATION_SYNC_KEY, projectId);
                redisTemplate.opsForList().leftPush(syncKey, syncMessage);
                redisTemplate.opsForList().trim(syncKey, 0, 999); // 保留最近1000条操作
                redisTemplate.expire(syncKey, 24, TimeUnit.HOURS);
                
                log.debug("操作同步: projectId={}, userId={}, operation={}, resourceId={}", 
                         projectId, userId, operationType, resourceId);
                
            } catch (Exception e) {
                log.error("同步操作异常: projectId={}, userId={}, operation={}", 
                         projectId, userId, operationType, e);
            }
        });
    }

    /**
     * 获取项目在线用户列表
     */
    public List<UserStatusMessage> getOnlineUsers(Long projectId) {
        try {
            String onlineKey = String.format(USER_ONLINE_KEY, projectId);
            Map<Object, Object> onlineUsers = redisTemplate.opsForHash().entries(onlineKey);
            
            // 检查是否为null
            if (onlineUsers == null || onlineUsers.isEmpty()) {
                return List.of();
            }
            
            return onlineUsers.values().stream()
                .map(obj -> (UserStatusMessage) obj)
                .filter(user -> user.getOnline())
                .toList();
                
        } catch (Exception e) {
            log.error("获取在线用户列表异常: projectId={}", projectId, e);
            return List.of();
        }
    }

    /**
     * 获取用户活动历史
     */
    public List<String> getUserActivityHistory(Long projectId, String userId, int limit) {
        try {
            String activityKey = String.format(USER_ACTIVITY_KEY, projectId);
            List<Object> activities = redisTemplate.opsForList().range(activityKey, 0, limit - 1);
            
            // 检查是否为null
            if (activities == null || activities.isEmpty()) {
                return List.of();
            }
            
            return activities.stream()
                .map(Object::toString)
                .filter(activity -> activity.startsWith(userId + ":"))
                .toList();
                
        } catch (Exception e) {
            log.error("获取用户活动历史异常: projectId={}, userId={}", projectId, userId, e);
            return List.of();
        }
    }

    /**
     * 获取项目操作历史
     */
    public List<CollaborationMessage> getOperationHistory(Long projectId, int limit) {
        try {
            String syncKey = String.format(OPERATION_SYNC_KEY, projectId);
            List<Object> operations = redisTemplate.opsForList().range(syncKey, 0, limit - 1);
            
            // 检查是否为null
            if (operations == null || operations.isEmpty()) {
                return List.of();
            }
            
            return operations.stream()
                .map(obj -> (CollaborationMessage) obj)
                .toList();
                
        } catch (Exception e) {
            log.error("获取操作历史异常: projectId={}", projectId, e);
            return List.of();
        }
    }

    /**
     * 批量更新用户状态
     */
    public void batchUpdateUserStatus(Long projectId, Map<String, String> userStatusMap) {
        Thread.startVirtualThread(() -> {
            try {
                String onlineKey = String.format(USER_ONLINE_KEY, projectId);
                
                // 检查用户状态映射是否为空
                if (userStatusMap == null || userStatusMap.isEmpty()) {
                    return;
                }
                
                userStatusMap.forEach((userId, status) -> {
                    UserStatusMessage statusMessage = (UserStatusMessage) redisTemplate.opsForHash().get(onlineKey, userId);
                    if (statusMessage != null) {
                        statusMessage.setStatus(status);
                        statusMessage.setLastActivity(LocalDateTime.now());
                        
                        redisTemplate.opsForHash().put(onlineKey, userId, statusMessage);
                        
                        // 广播状态更新
                        messagingTemplate.convertAndSend(
                            "/topic/collaboration/" + projectId + "/users",
                            statusMessage
                        );
                    }
                });
                
                log.info("批量更新用户状态: projectId={}, userCount={}", projectId, userStatusMap.size());
                
            } catch (Exception e) {
                log.error("批量更新用户状态异常: projectId={}", projectId, e);
            }
        });
    }

    /**
     * 清理过期状态
     */
    public void cleanupExpiredStatus(Long projectId) {
        Thread.startVirtualThread(() -> {
            try {
                String onlineKey = String.format(USER_ONLINE_KEY, projectId);
                Map<Object, Object> onlineUsers = redisTemplate.opsForHash().entries(onlineKey);
                
                // 检查是否为null或空
                if (onlineUsers == null || onlineUsers.isEmpty()) {
                    return;
                }
                
                LocalDateTime now = LocalDateTime.now();
                LocalDateTime expireTime = now.minusMinutes(30); // 30分钟无活动视为离线
                
                onlineUsers.forEach((userId, userObj) -> {
                    UserStatusMessage user = (UserStatusMessage) userObj;
                    if (user.getLastActivity().isBefore(expireTime)) {
                        userOffline(projectId, user.getUserId());
                    }
                });
                
                log.debug("清理过期状态完成: projectId={}", projectId);
                
            } catch (Exception e) {
                log.error("清理过期状态异常: projectId={}", projectId, e);
            }
        });
    }

    /**
     * 对象转JSON字符串
     */
    private String objectToJson(Object obj) {
        // 使用Jackson进行JSON序列化
        try {
            if (obj == null) {
                return "{}";
            }
            // 这里应该使用实际的JSON库，比如Jackson
            // 例如: return new ObjectMapper().writeValueAsString(obj);
            return obj.toString();
        } catch (Exception e) {
            log.warn("对象转JSON失败: {}", e.getMessage());
            return "{}";
        }
    }
}